<?php
#+------------------------------------------------------------------
#| 普通的。
#+------------------------------------------------------------------
#| Author:Janmas Cromwell <janmas-cromwell@outlook.com>
#+------------------------------------------------------------------
declare(strict_types=1);

namespace form\element\form;

use \Exception;
use form\element\form\traits\Label;
use form\element\traits\Classes;
use form\element\traits\Css;
use form\element\traits\Id;
use form\element\traits\Js;
use form\Form;

/**
 * @method self type(string $type) 切换输入框类型
 * @method self placeholder(string $string) 设置input等的placeholder属性
 * @method self value(string|array $value) 设置input等的value属性
 * @method self prepend(string $string) 输入框等的前缀
 * @method self append(string $string) 输入框等的后缀
 * @method self url(string $string) 上传地址
 * @method self file(string $file) 裁剪组件的已上传文件地址
 * @method self maxLength(int $length) 设置输入框或者文本域最长文字数量
 * @method self max(int $max) 数字输入框最大数字
 * @method self min(int $min) 数字输入框最小数字
 * @method self step(int $step) 数字输入框步进值
 * @method self multiple(bool $mutiple) 是否多选
 * @method self delimiter(string $delimiter)表格输入框的定界符
 *
 */
abstract class Column implements ColumnInterface
{

    use Js, Css, Id, Classes;

    /**
     * 样式类型 见form 元素布局属性
     * @var string
     */
    protected $style = 'normal';

    protected $isFile = false;
    #--------------一下都是元素本身属性------------------

    /**
     * name属性
     * @var string
     */
    protected $name = '';

    /**
     * label文字
     * @var string
     */
    protected $label = '';

    /**
     * label的class名
     * @var string
     */
    protected $labelClass = '';

    /**
     * 提示文字
     * @var string
     */
    protected $tips = '';

    /**
     * 是否只读
     * @var bool
     */
    protected $readonly = false;

    /**
     * 是否禁用
     * @var bool
     */
    protected $disbaled = false;

    /**
     * 是否必填
     * @var bool
     */
    protected $required = false;

    /**
     * 记忆开关
     * @var bool
     */
    protected $autocomplete = true;

    #============================================以下为功能函数============================================

    public function __construct(string $name, string $style)
    {
        $this->name = $name;
        $this->style = $style;
    }

    /**
     * 表单元素的样式 内联、普通、垂直
     * @param string $style
     * @return $this
     */
    public function scene(string $style)
    {
        $this->style = $style;
        return $this;
    }

    /**
     * 创建一个表单元素
     * @param string $name
     * @param string $type
     * @param string $style
     * @return Input|mixed
     * @throws Exception
     */
    public static function create(string $name = '', string $type = 'input', string $style = 'normal')
    {
        $type = self::camelize($type);
        $class = __NAMESPACE__ . '\\' . $type;
        if (class_exists($class)) {
            return new $class($name, $style);
        } else {
            $const = strtoupper($type) . '_INPUT';
            $class = Input::class;
            if (defined("$class::$const")) {
                return (new Input($name, $style))->type(strtolower($type));
            }
        }
        throw new Exception(sprintf('不存在的dom类型[%s]', $type));
    }

    #===========================以下为属性设置函数 后续不需要处理的属性用__call魔术函数自动设置========================

    /**
     * 设置label文字
     * @param string $label
     * @return $this
     */
    public function label(string $label = '', $class = '')
    {
        $this->label = $label;
        $this->labelClass = $class;
        return $this;
    }

    /**
     * 设置input记忆功能开关
     * @param bool $open
     * @return $this
     */
    public function autocomplete(bool $open = true)
    {
        $this->autocomplete = $open;
        return $this;
    }

    /**
     * 设置只读
     * @param bool $readonly
     * @return $this
     */
    public function readonly(bool $readonly = false)
    {
        $this->readonly = $readonly;
        return $this;
    }

    /**
     * 设置禁用
     * @param bool $disabled
     * @return $this
     */
    public function disabled(bool $disabled = false)
    {
        $this->disabled = $disabled;
        return $this;
    }

    /**
     * 设置tips提醒文字
     * @param string $tips
     * @return $this
     */
    public function tips(string $tips)
    {
        $this->tips = $tips;
        return $this;
    }

    #=========================以下为属性获取函数 所有都是protected只在实例内使用外部不可获取=============================================

    /**
     * 获取禁用字符
     * @return string
     */
    protected function getDisabled(): string
    {
        if ($this->disbaled) return ' disabled';
        return '';
    }

    /**
     * 获取提示信息
     * @return string
     */
    protected function getTips(): string
    {
        return empty($this->tips) ? '' : <<<HTML
 <small id="tips_$this->name" class="text-muted">$this->tips</small>
HTML;

    }

    /**
     * 获取label文字
     * @return string
     */
    protected function getLabel(): string
    {
        return empty($this->label) ? $this->name : $this->label;
    }

    protected function getLabelClass(): string
    {
        if ($this->style == Form::INLINE) {
            return 'sr-only';
        }
        return is_array($this->labelClass) ? implode(' ', $this->labelClass) : $this->labelClass;
    }

    /**
     * @return bool
     */
    protected function getRequired(): string
    {
        if ($this->required) {
            return ' required';
        }
        return '';
    }

    /**
     * @return
     */
    public function getReadonly(): string
    {
        if ($this->readonly) {
            return ' readonly';
        }
        return '';
    }

    /**
     * @return bool
     */
    protected function getAutocomplete(): string
    {
        if (!$this->autocomplete) {
            return ' autocomplete="off"';
        }
        return '';
    }

    #=========================================以下为构建html函数==========================================

    /**
     * 生成 仅此函数对外开放 其他normal之流的函数都是根据form传来的类型对应生成不同种类的元素
     * @return mixed
     */
    public function generate()
    {
        $method = $this->style;
        return $this->$method();
    }

    /**
     * 普通form
     * @return mixed
     */
    abstract protected function normal();

    /**
     * 垂直型
     * @return mixed
     */
    abstract protected function vertical();

    /**
     * 内联型
     * @return mixed
     */
    abstract protected function inline();

    /**
     * 不想写成员属性设置函数了 用这个吧先
     * @param $name
     * @param $arguments
     * @return $this
     * @throws Exception
     */
    public function __call($name, $arguments)
    {
        if (property_exists($this, $name)) {
            $this->$name = $arguments;
            return $this;
        }

        throw new \Exception('不存在该属性');
    }

    protected static function camelize($uncamelized_words, $separator = '_')
    {
        $uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words));
        return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator);
    }

    /**
     * @return bool
     */
    public function isFile(): bool
    {
        return $this->isFile;
    }


}